package org.gitman.agent.gui;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.FlowLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Calendar;
import java.util.Random;

import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;

import org.gitman.agent.platform.AddedAgentInfo;
import org.gitman.agent.platform.Agent;
import org.gitman.agent.platform.AgentManager;
import org.gitman.agent.platform.AgentState;
import org.gitman.agent.platform.PlatformManager;

public class AddAgentDialog extends JDialog implements ActionListener {

	private Component parent;
	private PlatformManager platformManager;
	private MainFrame mainFrame;
	private AddedAgentInfo info;
	private final ColorHolder colorHolder;
	private AddAgentTableModel addAgentTableModel;
	private JLabel start, end;
	
	public AddAgentDialog(final PlatformManager platformManager, Component parent, final MainFrame mainFrame){
		setSize(500, 330);
		info = new AddedAgentInfo();
		this.parent = parent;
		this.platformManager = platformManager;
		this.mainFrame = mainFrame;
		setAlwaysOnTop(true);
		setTitle("Add agent");
		setLayout(new BorderLayout());
		JPanel upperPanel = new JPanel(new BorderLayout());
		upperPanel.setBorder(BorderFactory.createTitledBorder("Options"));
		JPanel colorPanel  =new JPanel(new FlowLayout());
		colorHolder = new ColorHolder(info);
		colorPanel.add(colorHolder);
		JButton nextColor = new JButton("Change color");
		nextColor.addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent arg0) {
				colorHolder.changeColor();				
			}
		});
		colorPanel.add(nextColor);
		upperPanel.add(colorPanel, BorderLayout.NORTH);
		JPanel optionsBody = new JPanel(new GridLayout(3,3));
		optionsBody.add(new JLabel("To set Agent select:"));
		optionsBody.add(new JLabel(""));
		optionsBody.add(new JLabel(""));
		optionsBody.add(new JLabel("Point from where it starts"));
		optionsBody.add(new JLabel("with LB double click"));
		start = new JLabel("-");
		optionsBody.add(start);
		optionsBody.add(new JLabel("And destiny point"));
		optionsBody.add(new JLabel("with RB double click"));
		end = new JLabel("-");
		optionsBody.add(end);
		upperPanel.add(optionsBody);
		
		add(upperPanel, BorderLayout.NORTH);
		
		addAgentTableModel = new AddAgentTableModel(platformManager);
		JTable table = new JTable(addAgentTableModel);
		table.getColumnModel().getColumn(0).setPreferredWidth(10);
		table.getColumnModel().getColumn(1).setPreferredWidth(60);
		table.getColumnModel().getColumn(2).setPreferredWidth(300);
		JScrollPane scrollPane = new JScrollPane(table);
		add(scrollPane, BorderLayout.CENTER);
		JPanel bottomPanel = new JPanel(new FlowLayout());
		JButton ok = new JButton("Add this agent");
		ok.addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent arg0) {
				try{
					if(info.getStartPoint() == null){
						throw new Exception("start point is null");
					}
					if(info.getEndPoint() == null){
						throw new Exception("end point is null");
					}
					if(info.getStartPoint() == info.getEndPoint()){
						throw new Exception("start and end points must be diffrent");
					}
					Agent factory = addAgentTableModel.getSelectedAgent();
					if(factory == null){
						throw new Exception("Select agent");
					}
					AgentManager agentManager = platformManager.getSimulation().getAgentManager();
					if(!agentManager.isStartPointOk(info.getStartPoint())){
						throw new Exception("other agent already have that start point: " + info.getStartPoint().getValue() + ", change it");
					}					
					Agent agent = factory.getInstance();
					agent.setColor(info.getColor());
					agent.setStartPoint(info.getStartPoint());
					agent.setEndPoint(info.getEndPoint());
					agent.setSimulation(platformManager.getSimulation());
					agent.setState(AgentState.ready);
					agentManager.addAgent(agent);
					setVisible(false);
				}catch (Exception e) {
					JOptionPane.showMessageDialog(mainFrame, e.getMessage(), "Error", JOptionPane.ERROR_MESSAGE);
				}
			}
		});
		JButton cancel = new JButton("Cancel");
		bottomPanel.add(ok);
		bottomPanel.add(cancel);
		cancel.addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent e) {
				setVisible(false);
			}
		});
		add(bottomPanel, BorderLayout.SOUTH);
	}

	@Override
	public void actionPerformed(ActionEvent arg0) {
		if(platformManager.getGraphEditor().getGraph() == null){
			JOptionPane.showMessageDialog(mainFrame, "First create graph", "Information", JOptionPane.INFORMATION_MESSAGE);
		}else if(platformManager.getGraphEditor().isEdited()){
			JOptionPane.showMessageDialog(mainFrame, "First finish editing graph. Ensure to click \"Finish Editing\" button", "Information", JOptionPane.INFORMATION_MESSAGE);
		}else{
			if(!isVisible()){
				info = new AddedAgentInfo();
				info.setAddAgentDialog(this);
				colorHolder.setInfo(info);
				platformManager.getSimulation().getAgentManager().setAddedAgentInfo(info);
				setLocation(parent.getLocationOnScreen());
				setStartpoinID("-");
				setEndpointID("-");
				setVisible(true);
			}
		}
	}

	private class ColorHolder extends JLabel{
		private Random rand;
		private AddedAgentInfo info;
		
		public ColorHolder(AddedAgentInfo info){
			super("This will be Agent color (id)");
			this.info = info;
			rand = new Random(Calendar.getInstance().getTimeInMillis());
			changeColor();
			setOpaque(true);
		}
		
		public void changeColor(){
			Color c = null;
			do{
				c = new Color(rand.nextInt(256), rand.nextInt(256), rand.nextInt(256));
			}while(!platformManager.getSimulation().getAgentManager().isColorOk(c));			
			info.setColor(c);
			setBackground(info.getColor());
		}
		
		public void setInfo(AddedAgentInfo info){
			this.info = info;
			changeColor();
		}
	}

	
	public void setStartpoinID(String id) {
		start.setText(id);
	}

	public void setEndpointID(String id) {
		end.setText(id);
	}

}
